/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable @typescript-eslint/no-explicit-any */
"use client";

import {
  Attachments,
  Bubble,
  Prompts,
  Sender,
  Welcome,
  useXAgent,
  useXChat,
} from "@ant-design/x";
import { createStyles } from "antd-style";
import React, { useEffect } from "react";
import {
  CloudUploadOutlined,
  FireOutlined,
  PaperClipOutlined,
  ReadOutlined,
  ReloadOutlined,
} from "@ant-design/icons";
import { Badge, Button, Space, Typography } from "antd";
import MarkdownIt from "markdown-it";
import OpenAI from "openai";

const md = MarkdownIt({
  html: true,
  breaks: true,
});

const renderMarkdown = (content: string) => (
  <Typography>
    {/* biome-ignore lint/security/noDangerouslySetInnerHtml: used in demo */}
    <div
      dangerouslySetInnerHTML={{
        __html: content ? md.render(content) : "",
      }}
    />
  </Typography>
);

const client = new OpenAI({
  baseURL: "https://dashscope.aliyuncs.com/compatible-mode/v1",
  apiKey: "sk-900afcb7477744188848ef3acaa4e740",
  dangerouslyAllowBrowser: true,
});

const useStyle = createStyles(({ token, css }) => {
  return {
    layout: css`
      width: 100%;
      height: 100%;
      border-radius: ${token.borderRadius}px;
      display: flex;
      font-family: AlibabaPuHuiTi, ${token.fontFamily}, sans-serif;
      .ant-prompts {
        color: ${token.colorText};
      }
    `,
    conversations: css`
      padding: 0 12px;
      flex: 1;
      overflow-y: auto;
    `,
    chat: css`
      height: 100%;
      width: 100%;
      max-width: 700px;
      margin: 0 auto;
      box-sizing: border-box;
      display: flex;
      flex-direction: column;
      padding: 16px;
      padding-bottom: 10px;
      gap: 16px;
    `,
    messages: css`
      flex: 1;
    `,
    placeholder: css``,
    sender: css`
      box-shadow: ${token.boxShadow};
    `,
    logo: css`
      display: flex;
      height: 72px;
      align-items: center;
      justify-content: start;
      padding: 0 24px;
      box-sizing: border-box;

      img {
        width: 24px;
        height: 24px;
        display: inline-block;
      }

      span {
        display: inline-block;
        margin: 0 8px;
        font-weight: bold;
        color: ${token.colorText};
        font-size: 16px;
      }
    `,
    addBtn: css`
      background: #1677ff0f;
      border: 1px solid #1677ff34;
      width: calc(100% - 24px);
      margin: 0 12px 24px 12px;
    `,
  };
});

interface PromptItem {
  key: string;
  description: string;
  icon: React.ReactNode;
}

const senderPromptsItems: PromptItem[] = [
  {
    key: "1",
    description: "任务统计",
    icon: (
      <FireOutlined
        style={{
          color: "#FF4D4F",
        }}
      />
    ),
  },
  {
    key: "2",
    description: "BUG统计",
    icon: (
      <ReadOutlined
        style={{
          color: "#1890FF",
        }}
      />
    ),
  },
];

const roles = {
  ai: {
    placement: "start",
    typing: {
      step: 5,
      interval: 20,
    },
    styles: {
      content: {
        borderRadius: 12,
      },
    },
    messageRender: renderMarkdown,
  },
  local: {
    placement: "end",
    styles: {
      content: {
        borderRadius: 12,
        backgroundColor: "rgba(255, 255, 255, 0.5)",
      },
    },
    messageRender: renderMarkdown,
  },
};

interface FileInfo {
  fileList: any[];
}

interface PromptInfo {
  data: {
    description: string;
  };
}

const ChatBox: React.FC<{ data: any }> = ({ data }) => {
  // ==================== Style ====================
  const { styles } = useStyle();

  // ==================== State ====================
  const [headerOpen, setHeaderOpen] = React.useState(false);
  const [content, setContent] = React.useState("");
  const [attachedFiles, setAttachedFiles] = React.useState<any[]>([]);
  // ==================== Runtime ====================
  const [agent] = useXAgent({
    request: async (
      info: any,
      callbacks: {
        onSuccess: (content: string) => void;
        onUpdate: (content: string) => void;
      }
    ) => {
      const { messages, message } = info;
      const { onSuccess, onUpdate } = callbacks;
      let content = "";
      try {
        const stream = await client.chat.completions.create({
          model: "qwen-plus",
          // if chat context is needed, modify the array
          messages: [{ role: "user", content: message }],
          // stream mode
          stream: true,
        });

        for await (const chunk of stream) {
          content += chunk.choices[0]?.delta?.content || "";
          onUpdate(content);
        }

        onSuccess(content);
      } catch (error) {
        // handle error
        // onError();
      }
    },
  });

  const { onRequest, messages } = useXChat({ agent });

  // ==================== Event ====================
  const onSubmit = (nextContent: string) => {
    if (!nextContent) return;
    onRequest(nextContent);
    setContent("");
  };

  const onPromptsItemClick = (info: PromptInfo) => {
    onRequest(info.data.description);
  };

  useEffect(() => {
    if (!data) return;
    onRequest(`
      请根据以下数据: ${JSON.stringify(data)} 返回 antd Table的代码,并根据dataSource中没有值的列帮我编写一个接口文档 要求这些没有值的可以编辑。
    `);
  }, [data]);

  const handleFileChange = (info: FileInfo) => setAttachedFiles(info.fileList);

  // ==================== Nodes ====================
  const placeholderNode = (
    <Space direction="vertical" size={16} className={styles.placeholder}>
      <Welcome
        variant="borderless"
        icon="https://mdn.alipayobjects.com/huamei_iwk9zp/afts/img/A*s5sNRo5LjfQAAAAAAAAAAAAADgCCAQ/fmt.webp"
        title="你好,我是国产大模型"
        description="我就是Qwen开发的人工智能助手"
        // extra={
        //   <Space>
        //     <Button icon={<ReloadOutlined />} onClick={() => {
        //       onRequest(data);
        //     }} />
        //   </Space>
        // }
      />
      <Prompts
        title="DeepSeek R1 模型的速度非常慢，暂时先用 Qwen Max 代替!!"
        styles={{
          list: {
            width: "100%",
            display: "flex",
            paddingTop: 10,
          },
          item: {
            flex: 1,
          },
        }}
        onItemClick={onPromptsItemClick}
      />
    </Space>
  );

  const items = messages.map(({ message, id, status }) => ({
    // key is required, used to identify the message
    key: id,
    role: status === "local" ? "local" : "ai",
    content: message,
  }));

  const attachmentsNode = (
    <Badge dot={attachedFiles.length > 0 && !headerOpen}>
      <Button
        type="text"
        icon={<PaperClipOutlined />}
        onClick={() => setHeaderOpen(!headerOpen)}
      />
    </Badge>
  );

  const senderHeader = (
    <Sender.Header
      title="Attachments"
      open={headerOpen}
      onOpenChange={setHeaderOpen}
      styles={{
        content: {
          padding: 0,
        },
      }}
    >
      <Attachments
        beforeUpload={() => false}
        items={attachedFiles}
        onChange={handleFileChange}
        placeholder={(type: string) =>
          type === "drop"
            ? {
                title: "Drop file here",
              }
            : {
                icon: <CloudUploadOutlined />,
                title: "Upload files",
                description: "Click or drag files to this area to upload",
              }
        }
      />
    </Sender.Header>
  );

  // ==================== Render =================
  return (
    <div className={styles.layout}>
      <div className={styles.chat}>
        {/* 🌟 消息列表 */}
        <Bubble.List
          items={[
            {
              content: placeholderNode,
              variant: "borderless",
            },
            ...items,
          ]}
          roles={roles}
          className={styles.messages}
        />
        {/* 🌟 提示词 */}
        <Prompts items={senderPromptsItems} onItemClick={onPromptsItemClick} />
        {/* 🌟 输入框 */}
        <Sender
          value={content}
          header={senderHeader}
          onSubmit={onSubmit}
          onChange={setContent}
          prefix={attachmentsNode}
          loading={agent.isRequesting()}
          className={styles.sender}
        />
      </div>
    </div>
  );
};

export default ChatBox;
